/* ** por compatibilidad se omiten tildes **
================================================================================
 TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
================================================================================
  definicion de funciones del scheduler
*/
#include "defines.h"
#include "screen.h"

#include "sched.h"
#include "mmu.h"

extern unsigned int pc[];
extern unsigned int ps[];
extern unsigned int px[];
extern void pintar_codigo(unsigned int tarea, unsigned int posicion);
extern void pintar_stack(unsigned int tarea, unsigned int posicion);
extern void pintar_shared(unsigned int tarea, unsigned int posicion);

unsigned short tareas[CANT_TAREAS];

int ciclo[CANT_TAREAS];
int actual;
int cantTareasActuales;
int shared[CANT_TAREAS];

void inicializar_scheduler() {
	unsigned int i;
	unsigned short indiceGDT = 3;	//Las tareas empiezan desde el indice 3 de la GDT
	
	//Cargamos los indices en la GDT para cada una de las tareas
	for (i=0; i < CANT_TAREAS; i++)
	{
		tareas[i] = indiceGDT;
		indiceGDT++;
		ciclo[i] = i;
		shared[i] = px[i];	//inicializamos los shared en sus posiciones originales.
	}	
  
  	actual = 0;
  	cantTareasActuales = 5;
}

unsigned short proximo_indice() {
	int proximo = actual;
	actual = actual + 1;
	if (actual >= cantTareasActuales){
		actual = 0;
	}
	
	
	return tareas[ciclo[proximo]];
}

void eliminar_tarea(unsigned int _cr3) {
	int tarea = identificarTarea(_cr3);
	
	if (tarea < 1)
		return;
	if (tarea > 5)
		return;
	
	tarea--; //en nuestro ciclo las tareas van del 0 al 4.
	int cicloNuevo[cantTareasActuales - 1];
	int i;
	int j = 0;
	for (i=0; i<cantTareasActuales; i++) {
		if (ciclo[i] == tarea)
			continue;
		cicloNuevo[j] = ciclo[i];
		j++;
	}
	cantTareasActuales--; //vamos a tener una tarea menos.
	for (i=0; i<cantTareasActuales; i++) {
		ciclo[i] = cicloNuevo[i];
	}
	if (actual >= cantTareasActuales){
		actual = 0;
	}
	unmapear_pagina(TASK_CODE, _cr3);
	unmapear_pagina(TASK_STACK, _cr3);
}


void setPage(unsigned int indice, unsigned int _cr3) {
	unsigned int direccion = INIT_LUCHA + indice*0x1000;
	mapear_pagina(TASK_SHARE, _cr3, direccion,7);
	unsigned int tarea = identificarTarea(_cr3);
	tarea--;
	shared[tarea] = direccion;
}

unsigned int identificarTarea(unsigned int _cr3) {
	unsigned int PDir_base = ((unsigned int)(_cr3 & ~0xFFF)) - 0x30000;
	PDir_base = PDir_base / 0x1000;
	PDir_base = PDir_base + 1;
	return PDir_base;
}

unsigned int estaViva(unsigned int tarea) { //devuelve 1 si esta viva, 0 si no
	tarea--; //en nuestro ciclo las tareas van del 0 al 4.
	unsigned int resultado = 0;
	int i;
	for (i=0; i<cantTareasActuales; i++) {
		if (ciclo[i] == tarea)
			resultado = 1;
	}
	return resultado;
}

unsigned int posicionCodigo(unsigned int _cr3) {
	unsigned int tarea = identificarTarea(_cr3);
	return posCodigo(tarea);
}

unsigned int posicionStack(unsigned int _cr3) {
	unsigned int tarea = identificarTarea(_cr3);
	return posStack(tarea);
}

unsigned int posicionShared(unsigned int _cr3) {
	unsigned int tarea = identificarTarea(_cr3);
	return posShared(tarea);
}

unsigned int posCodigo(unsigned int tarea) {
	tarea--; //en nuestro ciclo las tareas van del 0 al 4.
	return ((pc[tarea] - INIT_LUCHA) / 0x1000);
}

unsigned int posStack(unsigned int tarea) {
	tarea--; //en nuestro ciclo las tareas van del 0 al 4.
	return ((ps[tarea] - INIT_LUCHA) / 0x1000);
}

unsigned int posShared(unsigned int tarea) {
	tarea--; //en nuestro ciclo las tareas van del 0 al 4.
	return ((shared[tarea] - INIT_LUCHA) / 0x1000);
}

void inicializar_arena() {
	int tarea;
	for (tarea=1; tarea<=5; tarea++) {
		pintar_codigo(tarea, posCodigo(tarea));
		pintar_stack(tarea, posStack(tarea));
		pintar_shared(tarea, posShared(tarea));
	}
}
